package com.lanyou.esb.cook.proxy.redis.persistent.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import redis.clients.jedis.exceptions.JedisException;

import com.lanyou.esb.cook.proxy.entity.IfAccTimes;
import com.lanyou.esb.cook.proxy.redis.persistent.base.BasePersistentRedis;
import com.lanyou.esb.cook.proxy.redis.proxy.impl.IfAccTimesJedisProxy;
import com.lanyou.esb.cook.proxy.redis.proxy.impl.IfAccTimesKeysJedisProxy;

/**
 * 持久化接口访问次数<br>
 * 描述：
 *
 * @author Davey.wu
 */
public class IfAccTimesPersistentRedis extends BasePersistentRedis<IfAccTimes> {
	/** Redis操作代理 **/
	private IfAccTimesJedisProxy jedisProxy;
	/** Redis操作代理 **/
	private IfAccTimesKeysJedisProxy keysJedisProxy;
	/****/
	// private Map<String, Boolean> map = new HashMap<>(this.getBatchAmount());
	// private List<String> absentKeys = new ArrayList<>();
	private static SimpleDateFormat DATEFORMAT = new SimpleDateFormat(
			"yyyyMMdd");

	public IfAccTimesPersistentRedis() {
		// 每30秒执行一次
		this.setCron("0 0/1 * * * ?");
		this.setName("IfAccTimesPersistentRedis");
		this.setGroup("IfAccTimesPersistentRedis");
		this.setJobClass(this.getClass());
	}

	@Override
	public void persistent() throws Exception {
		List<IfAccTimes> list = new ArrayList<>(this.getBatchAmount());
		Map<String, Boolean> map = new HashMap<>(this.getBatchAmount());
		List<String> absentKeys = new ArrayList<>();
		list.clear();
		map.clear();

		Map<String, Integer> values = null;
		List<IfAccTimes> objects = null;
		List<String> keys = null;
		//List<String> absentKeys = new ArrayList<>();
		while (true) {
			try {
				absentKeys.clear();
				keys = this.keysJedisProxy.spopAsStr(
						this.keysJedisProxy.getKey(), this.getBatchReadSize());
				// 没有数据，返回
				if (keys == null || keys.isEmpty()) {
					break;
				}
				for (String key : keys) {
					// 排除重复的更新
					if (heveRepeatKey(key, map)) {
						continue;
					}
					map.put(key, true);
					absentKeys.add(key);
				}
				if (absentKeys.isEmpty()) {
					continue;
				}
				keys.clear();
				for (String key : absentKeys) {
					keys.add(key.substring(0,
							key.lastIndexOf(IfAccTimesJedisProxy.KEY_SEPARATOR)));
				}
				// 获取次数
				values = this.jedisProxy.getInt(keys);
				if (values == null || values.isEmpty()) {
					continue;
				}
				// TODO,更新失败怎么办？ 更新REDIS数据
				this.jedisProxy.decrBy(values);

				objects = getObjectFromKey(absentKeys, values);
				if (objects == null || objects.isEmpty()) {
					continue;
				}
				list.addAll(objects);
				// 达到批量保存的数目，将数据保存到数据库
				if (list.size() >= this.getBatchAmount()) {
					getService().save(list);
					list.clear();
					continue;
				}
			} catch (Exception e) {
				// e.printStackTrace();
				if (e instanceof JedisException) {
					break;
				}
				// TODO 如果是将字符串转换成对象时出错，继续读后面的数据
				objects = null;
			}
		}
		// 保存剩余的数据
		getService().save(list);
		list.clear();
		map.clear();
	}

	/**
	 * 分解键值
	 * 
	 * @param key
	 * @return
	 */
	private List<IfAccTimes> getObjectFromKey(List<String> keys,
			Map<String, Integer> values) {
		if (keys == null || keys.isEmpty()) {
			return null;
		}
		List<IfAccTimes> result = new ArrayList<>(keys.size());
		for (String key : keys) {
			String[] fields = key.split(IfAccTimesJedisProxy.KEY_SEPARATOR);
			if (fields == null || fields.length != 5) {
				continue;
			}
			IfAccTimes ifAccTimes = new IfAccTimes();

			try {
				ifAccTimes.setFieldId(fields[0]);
				ifAccTimes.setSystemId(fields[1]);
				ifAccTimes.setIfId(fields[2]);
				ifAccTimes.setStatDate(DATEFORMAT.parse(fields[3]));
				ifAccTimes.setIfName(fields[4]);
				// 获取接口调用次数
				Integer times = values.get(key.substring(0,
						key.lastIndexOf(IfAccTimesJedisProxy.KEY_SEPARATOR)));
				if (times == null) {
					times = 0;
				}
				ifAccTimes.setTimes(times);
				result.add(ifAccTimes);
			} catch (ParseException e) {
				ifAccTimes = null;
			}
		}

		return result;
	}

	/**
	 * 判断是否存在重复的键
	 * 
	 * @param key
	 * @param map
	 * @return
	 */
	private boolean heveRepeatKey(String key, Map<String, Boolean> map) {
		if (map.size() == 0) {
			return false;
		}
		if (map.get(key) != null) {
			return true;
		}
		return false;
	}

	public IfAccTimesJedisProxy getJedisProxy() {
		return jedisProxy;
	}

	public void setJedisProxy(IfAccTimesJedisProxy jedisProxy) {
		this.jedisProxy = jedisProxy;
	}

	public IfAccTimesKeysJedisProxy getKeysJedisProxy() {
		return keysJedisProxy;
	}

	public void setKeysJedisProxy(IfAccTimesKeysJedisProxy keysJedisProxy) {
		this.keysJedisProxy = keysJedisProxy;
	}

}
